package oauth;

import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;



import setup.Config;
import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuth.Parameter;
import net.oauth.OAuthMessage;
import net.oauth.OAuthServiceProvider;
import net.oauth.client.OAuthClient;
import net.oauth.client.httpclient4.HttpClient4; 

/**
 * Oauth handler class for handling oauth with the hz servers. 
 * Copyright 2011 InterGroup project.
 * @version 25-11-2011
 */
public class OAuthHandler{
	private static OAuthHandler INSTANCE; 
	private Config config;
	private OAuthAccessor accessor;
	private OAuthClient client;
	
	/**
	 * OAuthHandler is a singleton. 
	 */
	private OAuthHandler(){
		this.config = null; 
		this.accessor = null; 
		this.client = null;
	}
	
	/**
	 * Get the object instance.
	 * @return The instance of OAuthHandler.
	 */
	public static OAuthHandler GETINSTANCE(){
		if(INSTANCE == null)
			INSTANCE = new OAuthHandler();
		
		return INSTANCE; 
	}
	 
	/**
	 * Set the configuration file.
	 * @param config An implementation of the Config interface.
	 */
	public void setConfig(Config config){
		this.config = config;
		this.accessor = getAccessor();
		this.client = new OAuthClient(new HttpClient4());	
	}
	
	/**
	 * Get the oauth accessor. 
	 * @return
	 */
	private OAuthAccessor getAccessor(){
		OAuthServiceProvider provider = new OAuthServiceProvider(
				config.getRequestTokenUri(), config.getAuthoriseUri(), config.getAccessTokenUri());
		OAuthConsumer consumer = new OAuthConsumer(config.getCallbackUri(), config.getConsumerKey(),
				config.getConsumerSecret(), provider);
		OAuthAccessor accessor = new OAuthAccessor(consumer);
		return accessor;
	}
	
	/**
	 * Get the authorization Url.
	 * @return
	 */
	public String getAuthorizationURL(){
		return accessor.consumer.serviceProvider.userAuthorizationURL 
				+ "?oauth_token=" + accessor.requestToken
				+ "&oauth_callback=" + accessor.consumer.callbackURL;
	}
		
	/**
	 * Set the oauth access token.
	 * @param secret The given access token by your oauth provider.
	 */
	public void setOauthAccessToken(String token){
		accessor.accessToken = token;
	}
	
	/**
	 * Set the oauth access token secret.
	 * @param secret The given access token secret by your oauth provider.
	 */
	public void setOauthAccessTokenSecret(String secret){
		accessor.tokenSecret = secret;
	}
	
	/**
	 * Send a request for a temporary request token.  
	 * @throws URISyntaxException 
	 * @throws OAuthException 
	 * @throws IOException 
	 */
	public void getRequestToken() throws IOException, OAuthException, URISyntaxException{
		client.getRequestToken(accessor);
		System.out.println("Token:" + accessor.requestToken + " || Secret:" + accessor.tokenSecret);
	}
	
	/**
	 * 
	 * @throws IOException
	 * @throws OAuthException
	 * @throws URISyntaxException 
	 */
	public void requestAccessToken(String verifier) throws IOException, OAuthException, URISyntaxException{
		List<Parameter> list = new ArrayList<Parameter>(); 
		list.add(new Parameter("oauth_verifier", verifier));  
		OAuthMessage om = client.getAccessToken(accessor, "POST", list);
		System.out.println("Token:" + accessor.accessToken + " || Secret:" + accessor.tokenSecret);
	}
	
	/**
	 * Send a request. 
	 * @param url
	 * @param parameters
	 * @return
	 * @throws IOException
	 * @throws OAuthException
	 * @throws URISyntaxException
	 */
	public String invoke(String url, Collection<? extends Entry> parameters) throws IOException, OAuthException, URISyntaxException{
		OAuthMessage response = client.invoke(accessor, url, parameters);		 
		String body = response.readBodyAsString();
		int index = body.indexOf("Message:");
		return body.substring(index + 1);
	}
}